package concurrecy;


import java.util.concurrent.*;

class Sandwich {
    private Toast top;
    private Toast bottom;

    public Sandwich(Toast top, Toast bottom) {
        this.top = top;
        this.bottom = bottom;
    }

    @Override
    public String toString() {
        return "Sandwich{" +
                "top=" + top +
                ", bottom=" + bottom +
                '}';
    }
}

class SandwichMaker implements Runnable {

    private BlockingQueue<Toast> upStream1;
    private BlockingQueue<Toast> upStream2;
    private BlockingQueue<Sandwich> queue = new LinkedBlockingQueue<>();

    public SandwichMaker(BlockingQueue<Toast> upStream1, BlockingQueue<Toast> upStream2) {
        this.upStream1 = upStream1;
        this.upStream2 = upStream2;
    }

    public BlockingQueue<Sandwich> getQueue() {
        return queue;
    }

    @Override
    public void run() {
        try {
            while(!Thread.interrupted()) {
                Toast up = upStream1.take();
                Toast bottom = upStream2.take();
                Sandwich sandwich = new Sandwich(up, bottom);
                System.out.println("make sandwich, " + sandwich);
                queue.put(sandwich);
            }
        } catch(InterruptedException e) {
            System.out.println("sandwich maker interrupted");
        }
    }
}


/**
 * 制作三明治
 */
public class ToastDemo1 {
    public static void main(String[] args) throws InterruptedException {
        ExecutorService service = Executors.newCachedThreadPool();

        Toaster toaster = new Toaster();
        Butter butter = new Butter(toaster.getQueue());
        Jammer jammer = new Jammer(toaster.getQueue());
        SandwichMaker sandwichMaker = new SandwichMaker(butter.getQueue(), jammer.getQueue());
        Consumer<Sandwich> consumer = new Consumer<>(sandwichMaker.getQueue());

        service.execute(toaster);
        service.execute(butter);
        service.execute(jammer);
        service.execute(sandwichMaker);
        service.execute(consumer);

        TimeUnit.SECONDS.sleep(10);
        service.shutdownNow();
    }
}
